/*
 * Copyright (c) 2018. QDU 2015 Java1 Team CompilationError
 */

package team.mai.antexpress.spring.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import team.mai.antexpress.dao.DepartmentDAO;
import team.mai.antexpress.dao.DesignationDAO;
import team.mai.antexpress.dao.PermissionGroupDAO;
import team.mai.antexpress.dao.UserDAO;
import team.mai.antexpress.entities.DepartmentEntity;
import team.mai.antexpress.entities.DesignationEntity;
import team.mai.antexpress.entities.PermissionGroupEntity;
import team.mai.antexpress.entities.UserEntity;
import team.mai.antexpress.services.DepartmentService;
import team.mai.antexpress.services.DesignationService;
import team.mai.antexpress.services.PermissionGroupService;
import team.mai.antexpress.services.UserService;
import team.mai.antexpress.spring.beans.LoginBean;

import javax.servlet.http.HttpServletResponse;

import static team.mai.antexpress.services.UserService.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class UserManagerController {

	@Autowired
	private UserDAO userDAO;
	@Autowired
	private DepartmentDAO departmentDAO;
	@Autowired
	private DesignationDAO designationDAO;
	@Autowired
	private PermissionGroupDAO permissionGroupDAO;
	@Autowired
	private UserService userService;
	@Autowired
	private DepartmentService departmentService;
	@Autowired
	private DesignationService designationService;
	@Autowired
	private PermissionGroupService permissionGroupService;
	@Autowired
	private LoginBean loginBean;

	@RequestMapping(value = "/admin/manage_users", method = RequestMethod.GET)
	public String viewUsers(ModelMap map, HttpServletResponse response) throws IOException {
		List<UserEntity> allUsers = userService.getAllUsers(loginBean.getUsername());
		if (allUsers == null) {
			response.sendError(401);
			return "error";
		}
		map.addAttribute("users", allUsers);
		putAllIntoMap(map);
		map.addAttribute("permissions", userDAO.getPermissionByUser(loginBean.getUsername()));
		return "admin/manage_users";
	}

	@RequestMapping(value = "/admin/delete_user", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> deleteUser(@RequestParam("id") int userId) {
		int result = userService.deleteUser(loginBean.getUsername(), userId);
		return getResponseJson(result);
	}

	@RequestMapping(value = "/admin/delete_users", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> deleteUsers(@RequestParam("ids[]") List<Integer> ids){
		int result = userService.deleteUsers(loginBean.getUsername(), ids);
		return getResponseJson(result);
	}

	@RequestMapping(value = "/admin/new_user", method = RequestMethod.GET)
	public String getNewUser(ModelMap map) {
		putAllIntoMap(map);
		return "admin/new_user";
	}

	@RequestMapping(value = "/admin/new_user", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> doNewUser(UserEntity userEntity) {
		System.out.println("Operator Name:" + loginBean.getUsername());
		int result = userService.insertUser(loginBean.getUsername(), userEntity);
		return getResponseJson(result);
	}

	@RequestMapping(value = "/admin/modify_user", method = RequestMethod.GET)
	public String doGetModifyUser(@RequestParam("id") int uid, ModelMap map, HttpServletResponse response) throws IOException {
		UserEntity user = userService.getUser(loginBean.getUsername(), uid);
		if (user == null) {
			response.sendError(401);
			return "error";
		}
		map.addAttribute("user", user);
		putAllIntoMap(map);
		return "admin/modify_user";
	}

	@RequestMapping(value = "/admin/modify_user", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> doPostModifyUser(UserEntity user) {
		if (user.getPassword() == null || user.getPassword().isEmpty()) {
			UserEntity userFromDb = userDAO.getUserById(user.getId());
			user.setPassword(userFromDb.getPassword());
		}
		int result = userService.updateUser(loginBean.getUsername(), user);
		return getResponseJson(result);
	}

	@RequestMapping(value = "/admin/check_username")
	@ResponseBody
	public Boolean checkUsername(@RequestParam("username") String username) {
		List<UserEntity> usersByName = userDAO.getUsersByName(username);
		return usersByName.isEmpty();
	}

	private void putAllIntoMap(ModelMap map) {
		List<PermissionGroupEntity> permissionGroups = permissionGroupDAO.getAllPermissionGroups();
		List<DepartmentEntity> departments = departmentDAO.getAllDepartments();
		List<DesignationEntity> designations = designationDAO.getAllDesignations();
		Map<Integer, PermissionGroupEntity> permissionGroupEntityMap = new HashMap<>();
		Map<Integer, DepartmentEntity> departmentEntityHashMap = new HashMap<>();
		Map<Integer, DesignationEntity> designationEntityHashMap = new HashMap<>();
		for (PermissionGroupEntity v : permissionGroups) {
			permissionGroupEntityMap.put(v.getId(), v);
		}
		for (DepartmentEntity v : departments) {
			departmentEntityHashMap.put(v.getId(), v);
		}
		for (DesignationEntity v : designations) {
			designationEntityHashMap.put(v.getId(), v);
		}
		map.addAttribute("permissionMap", permissionGroupEntityMap);
		map.addAttribute("departmentMap", departmentEntityHashMap);
		map.addAttribute("designationMap", designationEntityHashMap);
	}

	private Map<String, Object> getResponseJson(int userServiceCode) {
		Map<String, Object> status = new HashMap<>();
		switch (userServiceCode) {
			case VALIDATION_ERROR:
				status.put("status", "error");
				status.put("errorMessage", "Invalid Username");
				break;
			case INTERNAL_ERROR:
				status.put("status", "error");
				status.put("errorMessage", "Internal Error");
				break;
			case INSUFFICIENT_PRIVILEGE:
				status.put("status", "error");
				status.put("errorMessage", "Insufficient Privilege");
				break;
			default:
				status.put("status", "success");
				status.put("id", userServiceCode);
		}
		return status;
	}
}
